Skip to main content

管理 GitOps 中的 Secret:Argocd-Vault-Plugin

· 10 min read

Argocd-Vault-Plugin(AVP) 是一个自定义的 ArgoCD 插件,这个插件旨在帮助解决 GitOps 和 Argo CD 的 Secret 管理问题。用于从 HashiCorp Vault 等秘密管理器中检索秘密并将其注入 Kubernetes YAML 文件中,从而无需依赖 Operator 或 Custom Resource,这使得它不仅可以用于 Secrets 资源,还可以能够 parameterize 任何 Kubernetes 资源,甚至是自定义资源。

本文将介绍如何使用 Argocd-Vault-Plugin 管理 GitOps 中的 Secret

先决条件

在开始本教程之前,请确保您已经部署ArgoCD/Vault。我们不会在本文中向您展示如何做到这一点,但您可以参考下面给出的文档和演示用例。

工作原理

该插件的工作原理是首先根据可以指定为环境变量或 YAML 文件内部的注释的路径从 Vault 等秘密管理器中检索值,然后将值注入到模板化的输出 yaml 中,该 yaml 使用 <> 作为模板标记。例如:

kind: Secret
apiVersion: v1
metadata:
name: example-secret
annotations:
avp.kubernetes.io/path: "path/to/secret"
type: Opaque
stringData:
password: <password-vault-key>

在上面的yaml中,可以看到有一个标准的Kubernetes Secret定义。有一个名为 password 的秘密,但值是 <password-vault-key> ,如果插件在Vault中找到 password-vault-key 密钥,它将注入一个值。

准备 Vault 环境

vault 部署后查看 vault-0 的日志来获取登录 token等信息

kubectl logs vault-0  -n vault 
WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory
and starts unsealed with a single unseal key. The root token is already
authenticated to the CLI, so you can immediately begin using Vault.

You may need to set the following environment variables:

$ export VAULT_ADDR='http://[::]:8200'

The unseal key and root token are displayed below in case you want to
seal/unseal the Vault or re-authenticate.

Unseal Key: 7MY282Sz3te29uktYXqAFEBZ04GMIs5fkceWYPzRwos=
Root Token: root

Development mode should NOT be used in production installations!

这时候,我们可以使用获取到的Root Token 进行登录。

你可以通过本地客户端登录

export VAULT_ADDR=https://vault.cloudnative.love/
vault login <your_token>

或者进入 vault-0 容器内登录

kubectl -n vault exec -it vault-0 -- sh
vault login <your_token>

登录后将看到如下提示

Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.

Key Value
--- -----
token <your_token>
token_accessor <your_token_accessors>
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]

创建 Vault 认证模式

在使用 avp 此之前,让我们快速了解一下 vault 常用的认身份验证方式

  • Userpass Authentication: 用户名密码身份验证
  • Token Authentication: 令牌身份验证,令牌身份验证自动启用。当您启动开发服务器时,输出显示一个 root 令牌。
  • AppRole Authentication(推荐):应用角色授权
  • Kubernetes Authentication(推荐): Kubernetes身份验证,可用于使用Kubernetes的 service account 令牌对 Vault 进行身份验证。这种身份验证方法可以轻松地将Vault令牌引入Kubernetes Pod。

下面我们来配置 vault 的身份验证

比较简单此处省略

配置 Argo-Vault-Plugin

要想让avp通过vault认证,我们可以将认证参数作为环境变量保存为secret,并通过envFrom传入repo-server的pod中:

      envFrom:
- secretRef:
name: argocd-vault-plugin-credentials

或者在avp命令中添加--secret-name指定包含认证参数的secret

argocd-vault-plugin generate --secret-name <namespace>:<name> .

不同认证模式所需环境变量参考官方文档 backends 部分

Userpass/Token/AppRole 认证所需环境变量

Userpass 所需环境变量

VAULT_ADDR: Your HashiCorp Vault Address
VAULT_TOKEN: Your Vault token
AVP_TYPE: vault
AVP_AUTH_TYPE: token

Token 所需环境变量

VAULT_ADDR: Your HashiCorp Vault Address
AVP_TYPE: vault
AVP_AUTH_TYPE: userpass
AVP_USERNAME: Your Username
AVP_PASSWORD: Your Password

AppRole 所需环境变量

VAULT_ADDR: Your HashiCorp Vault Address
AVP_TYPE: vault
AVP_AUTH_TYPE: approle
AVP_ROLE_ID: Your AppRole Role ID
AVP_SECRET_ID: Your AppRole Secret ID

以AppRole为例创建secret

kubectl create secret generic argocd-vault-plugin-credentials \
--from-literal=VAULT_ADDR=vault.cloudnative.love \
--from-literal=AVP_TYPE=vault \
--from-literal=AVP_AUTH_TYPE=approle \
--from-literal=AVP_ROLE_ID=6f944878-1e02-c842-9251-5d8caa1af3f8 \
--from-literal=AVP_SECRET_ID=8e4732c5-5210-37a6-8d9b-2338d96b8018 \
--type=Opaque \
--dry-run=client -oyaml

生产如下内容

apiVersion: v1
data:
AVP_AUTH_TYPE: YXBwcm9sZQ==
AVP_ROLE_ID: NmY5NDQ4NzgtMWUwMi1jODQyLTkyNTEtNWQ4Y2FhMWFmM2Y4
AVP_SECRET_ID: OGU0NzMyYzUtNTIxMC0zN2E2LThkOWItMjMzOGQ5NmI4MDE4
AVP_TYPE: dmF1bHQ=
VAULT_ADDR: dmF1bHQuY2xvdWRuYXRpdmUubG92ZQ==
kind: Secret
metadata:
creationTimestamp: null
name: argocd-vault-plugin-credentials
type: Opaque

通过 argocd-cm ConfigMap安装已被移除(旧选项,从ArgoCD版本 2.6.0 弃用),通过sidecar容器安装(新选项,ArgoCD版本 2.4.0 支持),因此我们将选择基于 sidecar 的选项。

测试插件

注意:仅 Vault KV-V2 后端支持版本控制。使用 KV-V1 Vault 指定的版本将被忽略,并将检索最新版本。

# enable kv-v2 engine in Vault
vault secrets enable -path=avp kv-v2
# create kv-v2 secret with two keys
vault kv put avp/argo-vault-plugin-example-secret user="secret_user" password="secret_password"

# create policy to enable reading above secret
# https://www.vaultproject.io/docs/concepts/policies
vault policy write avp-policy - <<EOF
path "avp/data/argo-vault-plugin-example-secret" {
capabilities = ["read"]
}
EOF

现在我们可以继续使用argocd-vault-plugin来部署ArgoCD应用程序。

参考此例子创建argocd appliction

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: example-secret
spec:
destination:
name: ""
namespace: default
server: "https://kubernetes.default.svc"
source:
path: .
repoURL: "[email protected]:SJFCS/arogcd-vault-plugin-demo.git"
targetRevision: HEAD
plugin:
name: argocd-vault-plugin
project: default
syncPolicy:
automated: null

查看并同步

argocd app list
argocd app get --refresh

最终检查生成的资源文件

kubectl  -n default get secret example-secret -ojson  |jq -r '.data | map_values(@base64d)'

该插件的一个优点是,如果Vault中的值发生变化,我们可以毫不费力地更新集群中的值。因此,更新vault中的值:

更新值

vault kv put avp/argo-vault-plugin-example-secret user="secret_user2" password="secret_password2"

这里需要hard-refresh,否则redis中的缓存的 mfst|argocd.argoproj.io/instance|vault-secret|* key会导致无法更新

argocd app get vault-secret --hard-refresh
kubectl -n default get secret example-secret -ojson |jq -r '.data | map_values(@base64d)'
argocd app diff 命令传递 --hard-refresh 标志。